#ifndef KEYFINDER_H
#define KEYFINDER_H

#include <QAbstractListModel>
#include <QGroupBox>
#include <QKeyEvent>
#include <QLabel>
#include <QLineEdit>
#include <QListView>
#include <QListWidget>
#include <QPainter>
#include <QVBoxLayout>
#include <QWidget>
#include <QDir>

#include "services/project/projectservice.h"

struct KeyFinderLineItem {
  int lineNumber = 0;
  QString lineContent;
  QString matchedContent;
};

struct KeyFinderFileItem {
  QString filePath;
  QString error;
  QList<KeyFinderLineItem> lines;
};
Q_DECLARE_METATYPE(KeyFinderFileItem)

class KeyFinderLinesWidget : public QWidget {
  Q_OBJECT
public:
  QListWidget *linesWidget;
  explicit KeyFinderLinesWidget(QWidget *parent = nullptr);
  void setLines(QList<KeyFinderLineItem> lines, QString filePath);
  void jumpToLine(int row);

private:
  QList<KeyFinderLineItem> p_lines;
  QString p_filePath;
};

class KeyFinderFileItemWidget : public QWidget {
  Q_OBJECT

public:
  KeyFinderLinesWidget *linesWidget;
  explicit KeyFinderFileItemWidget(QWidget *parent = nullptr);
  void setItem(KeyFinderFileItem item);
  int countRow();
  int getRow();
  void setIndex(int row);
  void jumpToSelectedItem();
  bool isSelectedFirst();
  bool isSelectedLast();
  void selectedPrev();
  void selectedNext();
  void unSelected();
  void scrollToRow(int row);

private:
  QGroupBox *groupBox;
  QVBoxLayout *groupBoxLayout;

  // signals:
  //   void scrollFileTo(int row);
};

class KeyFinderLineItemWidget : public QWidget {
  Q_OBJECT

public:
  explicit KeyFinderLineItemWidget(KeyFinderLineItem *line,
                                   QWidget *parent = nullptr);
};

class KeyFinderSingleFileListModel : public QAbstractListModel {
  Q_OBJECT

public:
  KeyFinderSingleFileListModel(QObject *parent = nullptr)
      : QAbstractListModel(parent) {}

  int rowCount(const QModelIndex &parent = QModelIndex()) const override;

  QVariant data(const QModelIndex &index,
                int role = Qt::DisplayRole) const override;
  bool setData(const QModelIndex &index, const QVariant &value,
               int role = Qt::EditRole) override;

  // 设置模型数据
  void setItems(const QList<KeyFinderFileItem> &newItems);
  void clear();

private:
  QList<KeyFinderFileItem> items; // 存储列表数据
  QMap<int, QSize> rowHeights;
};

class KeyFinderLineEdit : public QLineEdit {
  Q_OBJECT

public:
  explicit KeyFinderLineEdit(QWidget *parent = nullptr) : QLineEdit(parent) {}

signals:
  void selectNextSignal();
  void selectPrevSignal();
  void jumpToSelectedSignal();

protected:
  void keyPressEvent(QKeyEvent *event) override;
};

class KeyFinder : public QWidget {
  Q_OBJECT

public:
  explicit KeyFinder(QWidget *parent = nullptr);
  void setSearchKey(QString key, bool isRegex = true);
  void setDefalutSearchPath(QString path);

public slots:
  void performSearch();

private:
  QVBoxLayout *mainLayout;
  KeyFinderLineEdit *searchArgInput;
  KeyFinderSingleFileListModel *resultFilesModel;
  QItemSelectionModel *resultFilesSelectionModel;
  QListView *resultFilesView;
  QList<KeyFinderFileItemWidget *> *fileItemWidgets;

  QString defalutSearchPath = ".";

  QList<KeyFinderFileItem> runRg(const QString searchTerm,
                                 const QString searchPath = ".",
                                 const bool isRegex = true);
  QList<KeyFinderFileItem> parseRgOutput(const QString rgOutput,
                                         const QString oOutput);
  void setItemWidget();

public slots:
  void selectPrevItem();
  void selectNextItem();
  void jumpToSelectedItem();

protected:
  void wheelEvent(QWheelEvent *event) override;
};

#endif // KEYFINDER_H

